package fiuba.webapp.action;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

import org.apache.struts2.ServletActionContext;

import fiuba.Constants;
import fiuba.model.Configuracion;
import fiuba.model.DeletedFile;
import fiuba.service.GenericManager;
import fiuba.webapp.action.HtmlEditorCommandsAction.FileInfo;

public class MultimediaAction extends BaseAction {
	/**
	 * 
	 */
	private static final long serialVersionUID = 4630698493879818260L;

	// Clase auxiliar para mostrar los datos
	public class DatoMultimedia {
		public String name;
		public String path;
		public boolean dir;
		public boolean img;
		public DatoMultimedia( String name, String path, boolean dir) {
			this.name = name;
			this.path = path;
			this.dir = dir;
			List<String> extensions = new ArrayList<String>();
			extensions.add("gif");
			extensions.add("jpeg");
			extensions.add("jpg");
			
        	String extension = "";
        	try {
        		extension = name.split("\\.")[name.split("\\.").length - 1];
        	} catch (Exception e) {};
        	
			this.img = false;
			if (! extension.equals("")) {
				this.img = extensions.contains(extension.toLowerCase());
			}
		}
		public String getName() {return name;}
		public String getPath() {return path;}
		public boolean isDir() {return dir;}
		public boolean isImg() {return img;}
	}
	
    private String path;
    private List<DatoMultimedia> items;
	private GenericManager<Configuracion,Long> configuracionManager;
	private GenericManager<DeletedFile,Long> deletedFileManager;
	
	// Para busquedas
	private String busqueda;

	// Para manejo del borrado
    private String accion = "";
    private String arch;

    // Para la maravilla del file upload
    private File NewFile;
    private String NewFileContentType;
    private String NewFileFileName;
    
    // Para mostrar la imagen
    private String initialPath;

	
    public String list() {
    	// Construimos el path completo
		String mediaPath = this.configuracionManager.get(1L).getMediaPath();
		// El initial path tiene que quedar
		this.initialPath = mediaPath;
		if (this.initialPath.charAt(this.initialPath.length() - 1) == '/') {
			this.initialPath = this.initialPath.substring(0, this.initialPath.length() - 1);
		}
    	
    	// Veo si hubo acciones
    	if (this.accion.equals("B")) this.borrar();
    	items = new ArrayList<DatoMultimedia>();
    	if (this.accion.equals("S")) return this.buscar();
    	if (this.accion.equals("U")) {
    		try {this.upload();}
    		catch (Exception e) {
    			saveMessage("Error al intentar subir el archivo");
    		}
    	}
    	
    	
    	// Inicializo la lista de items
		if (path == null || path.equals("")) path = "/";
		// medidas de seguridad: empieza con "/" y no tiene ".."
		if (path.charAt(0) != '/') path = "/";
		if (path.contains("..")) path = "/";
		// Directorio desde donde miro
        String lookupDir = ServletActionContext.getServletContext().getRealPath(mediaPath) + path;
        File dirPath = new File(lookupDir);
        if (!dirPath.exists()) { // Si no existe, vamos al raiz y ya
        	log.debug("Directorio que no existe: " + lookupDir);
        	path = "/";
        	lookupDir = ServletActionContext.getServletContext().getRealPath(mediaPath) + "/";
            dirPath = new File(lookupDir);
            if (!dirPath.exists()) {
            	log.debug("Directorio raiz que no existe: " + lookupDir);
            	return SUCCESS;
            }
        }
        // Recorro carpetas y archivos
		if (! path.equals("/") ) { // Agrego el ".." si es necesario
        	items.add(
        			new DatoMultimedia("..",path.substring(0, path.lastIndexOf('/')) ,true)
        	);
		}
        File[] archs = dirPath.listFiles();
        for (int i=0; i < archs.length; i++) {
            File arch = archs[i];
            if (! arch.getName().startsWith(".")) { // Devolver solo si empieza sin punto
    			String pathRelativo = "/";
    			if (! path.equals("/") ) {
    				pathRelativo = path + "/";
    			}
            	items.add(
            			new DatoMultimedia(arch.getName(),pathRelativo ,arch.isDirectory())
            	);
            }
        }
        return SUCCESS;
    }
    
    private void borrar() {
    	String completeFilePath ="";
    	File srcPath;
    	// Obtengo el archivo origen
    	try {
    		String mediaPath = this.configuracionManager.get(1L).getMediaPath();
	    	completeFilePath = ServletActionContext.getServletContext().getRealPath(mediaPath) 
	    		+ this.path + "/" + this.arch;
	    	srcPath = new File(completeFilePath);
	        if (!srcPath.exists()) { // Si no existe, vamos al raiz y ya
	    		saveMessage("El archivo no existe, imposible borrar");
	    		return;
	        }
    	}
    	catch (Exception e) {
    		saveMessage("Error inesperado al acceder al archivo");
    		return;
    	}
    	
    	// Obtengo el archivo destino
    	File dstPath = null;
    	try {
    		String deletedMediaPath = this.configuracionManager.get(1L).getDeletedMediaPath();
	    	String destDir = ServletActionContext.getServletContext().getRealPath(deletedMediaPath) + "/";
	    	boolean existe = true;
	    	int intentos = 0;
	    	while (existe) {
		    	int filename = new Double(Math.random() * 1000000).intValue();
	    		String pathFinal = destDir + filename; 
	    		dstPath = new File(pathFinal);
	    		existe = dstPath.exists();
	    		intentos ++;
	    		if (intentos > 10) {
	        		saveMessage("Imposible generar archivo nuevo");
	        		return;
	    		}
	    	}
    		
    	}
    	catch (Exception e) {
    		saveMessage("Error inesperado al mover al archivo");
    		return;
    	}    	
    	// Muevo el archivo y registro que se borro
    	DeletedFile df = new DeletedFile();
    	df.setCurrentPath(dstPath.getAbsolutePath());
    	df.setLastPath(srcPath.getAbsolutePath());
    	df.setFileName(this.arch);
    	srcPath.renameTo(dstPath);
    	this.deletedFileManager.save(df);
		saveMessage("Archivo borrado");
    }

    public String buscar() {
    	// Armo el string de palabras a buscar
    	if (this.busqueda == null) return SUCCESS;
    	String[] palabrasArr = busqueda.split(" ", -1);
    	for (int i = 0; i < palabrasArr.length; i++) {
    		palabrasArr[i] = palabrasArr[i].trim().toLowerCase();
    	}
    	if (palabrasArr.length == 0 ) return SUCCESS;
    	// Recorro el dir inicial y todos sus subdirs
		String mediaPath = this.configuracionManager.get(1L).getMediaPath();
        String lookupDir = ServletActionContext.getServletContext().getRealPath(mediaPath);
        File dirPath = new File(lookupDir);
        if (!dirPath.exists()) { // Si no existe, vamos al raiz y ya
        	log.debug("Directorio que no existe: " + lookupDir);
        	path = "/";
        	lookupDir = ServletActionContext.getServletContext().getRealPath(mediaPath) + "/";
            dirPath = new File(lookupDir);
            if (!dirPath.exists()) {
            	log.debug("Directorio raiz que no existe: " + lookupDir);
            	return SUCCESS;
            }
        }
        
        List<String[]> directorios = new ArrayList<String[]>();
        String[] dirData = new String[2];
        dirData[0] = lookupDir;
        dirData[1] = "/";
        directorios.add(dirData);
        
        while(directorios.size() > 0) {
        	String[] currentDirData = directorios.get(0); 
        	directorios.remove(0);
        	String currentDir = currentDirData[0]; 
        	String currentPath = currentDirData[1]; 
        	File dir = new File(currentDir);
            File[] archs = dir.listFiles();
            for (int i=0; i < archs.length; i++) {
                File arch = archs[i];
                if (! arch.getName().startsWith(".")) { // Devolver solo si empieza sin punto
                	if (arch.isDirectory()) {
                        dirData = new String[2];
                        dirData[0] = arch.getAbsolutePath();
                        dirData[1] = currentPath + arch.getName() + "/";
                		directorios.add(dirData);
//                		log.debug("AGregado: " + arch.getAbsolutePath());
                	}
                	else {
                		boolean match = false;
                		for (int ipal = 0; ipal < palabrasArr.length; ipal++) {
                			int pos = arch.getName().toLowerCase().indexOf(palabrasArr[ipal]);
                			if (pos >= 0) match = true;
                		}
                		// Si el archivo sigue el criterio, lo muestro
                		if (match) {
                			items.add(new DatoMultimedia(arch.getName(),currentPath,arch.isDirectory()));
                		}
                	}
                }
            } // para los archivos del directorio
        } // Mientras haya directorios
    	
    	return SUCCESS;
    }
    
    public void upload() throws Exception {
		String mediaPath = this.configuracionManager.get(1L).getMediaPath();
        String uploadDir = ServletActionContext.getServletContext().getRealPath(mediaPath) + path;
        File fileUploadDir = new File(uploadDir);
        if (!fileUploadDir.exists()) { // Si no existe, no puedo hacer nada
        	log.debug("DIRECTORIO DONDE QUIERE SUBIR ARCHIVO NO EXISTE: " + path);
        	return;
        }
        //Obtener los datos
        InputStream stream = new FileInputStream(NewFile);

        if (! path.equals("/")) uploadDir = uploadDir + "/";

        //Grabar en la salida
        OutputStream bos = new FileOutputStream(uploadDir + NewFileFileName);
        int bytesRead;
        byte[] buffer = new byte[8192];

        while ((bytesRead = stream.read(buffer, 0, 8192)) != -1) {
            bos.write(buffer, 0, bytesRead);
        }
        bos.close();
        stream.close();
        saveMessage("El archivo fue subido correctamente");
    }
    
    

	public String getPath() {
		return path;
	}


	public void setPath(String path) {
		this.path = path;
	}


	public List<DatoMultimedia> getItems() {
		return items;
	}


	public void setItems(List<DatoMultimedia> items) {
		this.items = items;
	}


	public void setConfiguracionManager(
			GenericManager<Configuracion, Long> configuracionManager) {
		this.configuracionManager = configuracionManager;
	}


	public String getAccion() {
		return accion;
	}


	public void setAccion(String accion) {
		this.accion = accion;
	}


	public String getArch() {
		return arch;
	}


	public void setArch(String arch) {
		this.arch = arch;
	}


	public GenericManager<Configuracion, Long> getConfiguracionManager() {
		return configuracionManager;
	}

	public void setDeletedFileManager(
			GenericManager<DeletedFile, Long> deletedFileManager) {
		this.deletedFileManager = deletedFileManager;
	}

	public String getBusqueda() {
		return busqueda;
	}

	public void setBusqueda(String busqueda) {
		this.busqueda = busqueda;
	}

	public File getNewFile() {
		return NewFile;
	}

	public void setNewFile(File newFile) {
		NewFile = newFile;
	}

	public String getNewFileContentType() {
		return NewFileContentType;
	}

	public void setNewFileContentType(String newFileContentType) {
		NewFileContentType = newFileContentType;
	}

	public String getNewFileFileName() {
		return NewFileFileName;
	}

	public void setNewFileFileName(String newFileFileName) {
		NewFileFileName = newFileFileName;
	}

	public String getInitialPath() {
		return initialPath;
	}

	public void setInitialPath(String initialPath) {
		this.initialPath = initialPath;
	}

}
